\section{TODO列表}


\section{默认参数值的传递表达}
\subsection{普通类型}
这种类型包括内置类型，int,char,QVariant支持的类。
这种可以直接使用QVariant表示，并且能够非常容易的检测。

\subsection{表达式参数值}
这种包括类似QChar(' '), QString("")，QFlags<???>()，
在FrontEngine中转换打包这个表达式，
传递到CompilerEngine进行编译相应的表达式，并传递到OperatorEngine中引用表达式结果。
表达式的结果应该在CompilerEngine中生成，因为底层不应该再调用上层。
不过这个表达式代码还是挺难生成的。

默认值表达式生成的执行逻辑优化：
1、目前是在FE中，检测表达式中的类类型，在AST查找时就明确生成这个类的实例，把这个类传递到IR生成类OE中使用。
这种实现没有灵活性，并且需要在后续的测试中不断加入新的默认值类型的处理。
2、现在，已经使用了更优化的方式，为默认值表达式生成一段IR代码，传递到IR生成类OE中使用。
一般默认值表达式不会太复杂，生成的IR代码也比较简单，也容易处理使用。
3、也许，后续还可以把这些默认值表达式缓存，把生成的IR代码也缓存，不需要每次使用的时候都重复处理了。

// 发现了点东西，拷贝IR指令时需要注意的。
/*
  可能就是api中说的，clone出来的Inst与原来的Inst有点不一样，没有Parent。如下所示：

  以下两名都能生成相同的一行指令，但前者生成的语句就会导致崩溃，后者生成的则无问题
  call void @_ZN6QFlagsIN2Qt10WindowTypeEEC2EMNS2_7PrivateEi(%class.QFlags* %toargx0, i32 -1)
  call void @_ZN6QFlagsIN2Qt10WindowTypeEEC2EMNS2_7PrivateEi(%class.QFlags* %toargx0, i32 -1)
*/


\subsection{void*类型}
这种是一个透明传递的QXxx*类型实例。

\section{模板方法的实例化}
\subsection{普通方法实例化}
\subsection{构造函数实例化}
默认情况下会生成Ctor\_Complete类型的实例。

\section{调用重载函数的查找确认}
查找最合适的调用函数。
这个应该在clang中有，不知道在哪？

基础原理，计算重载函数的参数匹配度，使用匹配度最高的那个。
匹配度计算，参数是否匹配。
1。名字匹配
2。对于构造，如果调用提供了参数，则忽略默认构造函数
3。函数的参数个数不能少于调用提供的参数个数。

经过这3步的过滤，效果还是比较好的。

\subsection{为实现名字决议的匹配的前置参数预转换}
描述：see #3
解决方法分两步，
第一步，在名字决议时检测这种情况并通过决议。
   检测方式，1）该类需要有拷贝构造函数，2）该参数不是引用或者指针类型参数。
第二步，在生成IR时，同样要检测这种情况，做相应的处理，
   处理，使用dereference(n)指令，直接解引类对象指针。

\section{返回的处理}
一般情况下，根据Decl中的返回值类型，把llvm::GenericValue转换成类对象指针或者原生数据类型值，
存储在QVariant中返回给调用端。

但有一种特殊情况，某方法应该返回的是类对象(structret)方式，但由于编译优化，
由于该类能够转换为i32类型存储，IR代码直接返回了一个i32类型值。
这种情况下，需要同时根据方法的Decl中返回值类型与IR中的返回值类型来决定调用后处理。

\section{类属性赋值的处理}
lcd.value = 5
lcd.range = 0..99
估计需要考虑检测是否是类的属性类型的symbol，再转换成相应的set函数调用。
ruby会生成一个"interval="方法调用，有一个参数为赋值表达式的方法调用。
这里的=号，无论在ruby离interval多远，都会被连接到property名字上当作一个方法名。

\section{类重载操作符的处理}
像==、!=、>、<等重载的操作符号。

\section{qApp全局变量的处理}
qtbinding中实例这个变量的方式是，通过继承出来一个假的Application或者CoreApplication类，
在这个类的初始化时设置ruby全局变量$qApp。

这种方式，实际也没有太多的技巧，也许可以考虑更好的方式。
使用rb\_define\_virtual\_variable方式，在C部分查找到相应的qApp并返回。
这是使用的尽量在C模块中集中实现所有的绑定功能，不需要在ruby中再做绑定的补丁。

\section{预编译头文件AST的应用}
可用。
不完善，修改了其中一个头文件，则需要重新生成ast文件。
如果实时生成，则速度太慢，上秒级。
可以考虑使用增量式的AST生成。

\chapter{Ruby&Qt}
\section{Ruby nil}
nil传递到Ruby C API之后会是什么类型的值，怎么表达的。
nil传递到C时是int类型的0。
区间0..99传递到Ruby C API之后会是什么类型，怎么表达的。
即Range类型(内部表示为T\_STRUCT类型)，需要扩展成两个参数：起始值与结束值。

\section{Ruby的层信号定义}
使用signals 'hit()', 'missed()', 'changed(int)'语法
处理过程：
在ruby继续类中，使用该语法定义
这个定义会生成一个signals(多维）哈希数组结合存储这些信号。
这个信号可以连接Qt原始类的slot，也可连接Ruby继承类的slot（自动检测，只要是变通方法即可）
可以使用Qt5::rbconnect方法，与Qt5::connectrb方法对应，表示信号是在ruby层定义的。
也许还需要一个Qt5::rbconnectrb方法，处理从ruby层的信号，连接到ruby层的slot。
还有一个默认的Qt5::QObject::connect，是使用qt层signal连接qt层的slot方法。
最后，几个连接模式全部完成后，把几种连接方式合并成为统一的通用方式。

在qtbindings中，也是使用类似的方式，但这些处理完全在ruby层实现的。
另外qtbindings中，slots需要显式指定，与signals一样。
而这里slots不需要显式指定，优先检测ruby层类是否有这个方法，如果有则优先使用，如果没有则使用qt层的slot方法。

\section{Ruby中继承Qt类的处理}

\section{Ruby的Object类已有方法的处理}
像display方法，如果在Qt类中还有这个方法，则无法正确的调用到Qt类的方法，
必须把Object类中的display方法undef掉，使用rb\_undef\_method函数。
类似的情况可能还有许多，但需要一个一个列出来。
这是还涉及到BasicObject类中的方法。
因为继承层次为BasicObject <- Object。

在ruby qtbinding项目中，它使用的是在ruby层重定义并覆盖这个方法的方式，
在qtruby4.rb文件中。
并且它使用的是覆盖整个Object类的方法，而不是针对某一个Qt类实例相应的修正。

\section{Ruby中new Qt类时，外带do |x| 块语法的处理}
怎么获取，获取之后怎么执行。
使用rb\_block\_given\_p()判断是否外带block语法，如果有，则直接rb\_yield(self)执行。

\section{ruby中动态注册Qt类}
目前的情况，先使用rb\_define\_class等来声明类，使用rb\_define\_method等声明方法。
这种需要预先列出所有的qt类，比较麻烦，也不够通用，不够有效率（启动注册上千个类）。
但是，在不预先注册qt类的情况下，ruby会把这个当作constant处理，
如Qt5::QStringAbc.new()语句，会执行到x\_Qt\_Constant\_missing函数中。
在这个函数中，动态注册该Qt类，并返回类对应的VALUE类型的值。

\section{clang与gcc兼容性问题}
\subsection{/usr/include/string.h:82:1: error: unknown type name '\_\_extern\_always\_inline'}
在使用clang编译时报错。
一种解决方式是使用-O0优化参数，能够避免这个报错。

\section{Qt库调试}
可以另行编译出Qt共享库，使用设置LD\_LIBRARY\_PATH方式，
用新编译出的库替换系统自带的库文件，这样可以比较方便的在Qt中插入代码调试。

\section{Qt类实例解引}
目前是存储在void*中，在qDebug()的时候需要根据实例类型执行解引，这就需要动态获取类是否能够支持的类型。
第一种方式是使用AST树进行查找，按照正常的调用函数方式。
第二种是使用dlopen/dlsym方式，这种方式也不会比第1种方式快，需要打开共享库文件，有磁盘操作。
第三种是把所有支持qDebug操作的类罗列出来，并批量写到代码中。

3:

\chapter{C++}
nm -s libhandby.so 中，符号为'U'的表示什么意思呢？
执行的时候报错：undefined symbol: \_ZN9SingletonI15QtObjectManagerE6m\_instE
这个'U'应该就是undefined的意思。

C++中的friend友元不能继承。

\section{参考}
ROOT/cling
llvm/vmkit
Graal/Truffle

